Skip to content

fixtures(google): SPARKLINE conformance rows - #772

Merged
hhimanshu merged 1 commit into
mainfrom
fixtures/766-sparkline-rows
Jul 28, 2026
Merged

fixtures(google): SPARKLINE conformance rows#772
hhimanshu merged 1 commit into
mainfrom
fixtures/766-sparkline-rows

Conversation

@hhimanshu

@hhimanshu hhimanshu commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

closes #766

Summary

The Google Sheets conformance rows for SPARKLINE, whose implementation merged in #770. Fixtures-only — the Check fixture / code separation CI job rejects any PR touching both these TSVs and code, which is why this is separate.

115 rows, every value observed in live Google Sheets. 114 to google.tsv; 1 to bugs.tsv — see below.

Why this took 115 rows and not 26

Ground truth started at 26 and grew across eight probe batches. Not one was planned. Each came from a review finding where two readings were equally plausible and only Sheets could adjudicate — and in several cases the plausible reading was wrong:

  • =SPARKLINE({1,2,3})=SPARKLINE({1,2,3})TRUE was read as identity is the parsed spec. The missing control, =SPARKLINE({1,2,3})=SPARKLINE({9,9,9}), is also TRUE. Every sparkline equals every other. That reversed the value model after it was already built.
  • DOLLAR#VALUE! but TO_DOLLARS"". Near-identical names, opposite answers.
  • TO_PERCENT"" while its structurally identical siblings were assumed to error. Three of the five-member TO_* family had the wrong answer.
  • PRODUCT with a lone sparkline is 0, not the multiplicative identity — invisible with two arguments, which is why it passed for a while.
  • MINA matching MAXA at 0 was a coin-flip until asked.

The one row in bugs.tsv

=MIN(SPARKLINE({1,2,3}),{})#REF! does not pass. This engine returns 0, because min_fn has no empty-array rule while max_fn does.

That divergence is pre-existing and has nothing to do with sparklines=MIN({}) is 0 on main with no sparkline involved. Fixing it would move MIN for unrelated inputs, so it is recorded rather than papered over, in the file this repo documents for captured values the engine does not yet match. It is non-blocking, counted, and flips to passing the moment #771 lands — at which point it moves to its category TSV.

The alternative was quietly dropping an inconvenient row. That is how ground truth gets curated into agreement with the implementation.

How to test

cargo test -p truecalc-core --test conformance
cargo test -p truecalc-core --test conformance -- --nocapture   # see the per-file tally

google.tsv is a blocking gate. The tally now prints what is actually enforced versus skipped, which #770 added after the previous coverage claim turned out to be overstated:

google.tsv: 128 rows — 83 enforced, 29 skipped (no recorded expected value), 16 skipped (reads authored cells)

The 29 have no recorded value because a rendered sparkline has no text projection; the 16 read authored cells the standalone runner cannot resolve. All 45 are asserted directly in crates/core/tests/sparkline.rs (47 tests) instead. That gap is #767.

Provenance

Every row came from the Google Sheets conformance pipeline — evaluated in a real spreadsheet, transcribed verbatim, never computed by this engine. The 14 pre-existing ARRAYFORMULA rows are untouched.

One methodological note worth recording: in an early batch, 9 probe formulas were written without a leading =, so Sheets stored them as literal text and returned plausible-looking garbage while the run reported success. It was caught by reading the values rather than trusting the exit status — and one of the nine was the control row that reversed the value model. Every later batch asserted the = prefix before running.

Test plan

  • cargo test -p truecalc-core --test conformance — 20 passed, 0 failed
  • google_conformance green as a blocking gate
  • 14 pre-existing ARRAYFORMULA rows byte-identical to main
  • Fixtures-only — no code paths touched, so the separation check passes
  • CI green

Related

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

115 rows exported from the Google Sheets conformance fixtures, evaluated
against live Sheets across eight probe batches. Every batch after the first
was triggered by a specific finding that could not be settled by argument.

114 of them go to google.tsv. The 115th,
`=MIN(SPARKLINE({1,2,3}),{})` → `#REF!`, is a known engine divergence and
goes to bugs.tsv, this repo's home for GS-captured rows the engine does not
yet match: MIN has no empty-array rule at all, so it answers 0 — for
`=MIN({})` too, with no sparkline involved. `=MAX({})` is `#REF!`, so MAX's
counterpart row passes. The gap predates sparklines and is unrelated to
them; fixing it from here would move MIN for inputs that have nothing to do
with this work. The row is recorded verbatim, so it flips to passing the
moment MIN is fixed and can then move to google.tsv.

The second batch supplied the control the first was missing:
`=SPARKLINE({1,2,3})=SPARKLINE({1,2,3})` → TRUE looked like evidence that a
sparkline's value identity is its parsed spec, but
`=SPARKLINE({1,2,3})=SPARKLINE({9,9,9})` → TRUE disproves it — every
sparkline compares equal to every other. COUNTUNIQUE (2 for different, 1
for identical) is what actually requires the spec to be retained. Two row
descriptions in that batch ("identity: different data is not equal",
"...different charttype is not equal") were written before the run and read
backwards against their own recorded TRUE; the recorded values, not the
descriptions, are the ground truth.

The third and fourth batches settled the currency/conversion split —
DOLLAR and FIXED reject a sparkline while the whole TO_* family answers ""
— plus the single-argument aggregates and the blanket numeric rejection
(ROUND, ABS, INT, unary minus and percent).

The fifth and sixth batches probe a sparkline arriving through a RANGE,
from a cell holding `=SPARKLINE(...)` (`Data!K1`, with 5 in `Data!K2`) —
how a real workbook delivers one. `=PRODUCT(Data!K1:K1)` is 0, so an
aggregate answers the same whichever way the sparkline arrived; the
two-cell rows cannot settle that alone, since 1 × 5 = 5 either way.
`=TYPE(Data!K1)` is 128: reading a cell is not a coercion point, despite
the empty display.

The seventh batch closes the aggregate family: every aggregate answers 0
when a sparkline is the only thing in scope — MAX, MIN, MAXA and MINA
included — with AVERAGE's #DIV/0! the single exception. MINA matching MAXA
was a coin-flip until probed: it had no implementation arm at all.

The eighth batch backs the one direct form that was still being inferred
from its range form (`=MIN(SPARKLINE({1,2,3}))` → 0) and finds a boundary:
an explicitly empty array argument outranks the sparkline skip
(`=MAX(SPARKLINE({1,2,3}),{})` → #REF!) while a text-only array does not
(`=MAX(SPARKLINE({1,2,3}),{"a"})` → 0).

Coverage: each charttype, an omitted charttype, colour options, ymin/ymax,
text inside the data, all-negative data, a genuine blank cell inside a real
source range, `bar` given three values, an unknown option key, an unknown
charttype value, a malformed options shape, the value-model probes, identity
and ordering against sparklines and scalars, the EQ/NE/GTE alias functions,
the three coercion seams, the TO_* family, presence (COUNTA, ISBLANK),
COUNTUNIQUE, and the aggregates direct, through a range, and against empty
and text-only arrays.

69 of google.tsv's 114 SPARKLINE rows are enforced by the conformance
runner. Of the other 45, 29 record an empty expected value (a rendered
chart has no text projection) and 16 read authored input cells the
standalone runner has no workbook to supply — it skips both, and now says
so per file (core#767). crates/core/tests/sparkline.rs asserts those cases
directly, the range rows against a seeded resolver.

One row is deliberately named as a parser artefact: `=SPARKLINE({1,,3})` →
`#ERROR!` is Sheets rejecting the array-literal syntax before SPARKLINE
runs, not a blank-cell rule. The `Data!H`/`Data!I` rows are the trustworthy
blank-cell probe and its all-present control.

Refs #766
@hhimanshu hhimanshu self-assigned this Jul 28, 2026
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Test Coverage by Category

Category Unit Tests Google Sheets Conformance Property Cases Total
Array 42 547/547 ✓ 1,000 (2×500) 1,589
Database 35 182/182 ✓ 3,500 (7×500) 3,717
Date 369 418/418 ✓ 2,500 (5×500) 3,287
Engineering 245 886/888 ⚠ 5,500 (11×500) 6,633
Filter 11 80/80 ✓ 4,500 (9×500) 4,591
Financial 149 1,208/1,208 ✓ 2,000 (4×500) 3,357
Info 0 256/256 ✓ 4,500 (9×500) 4,756
Logical 121 263/263 ✓ 3,500 (7×500) 3,884
Lookup 69 392/392 ✓ 1,000 (2×500) 1,461
Math 536 2,006/2,006 ✓ 8,000 (16×500) 10,542
Operator 87 250/250 ✓ 7,500 (15×500) 7,837
Parser 83 92/92 ✓ 4,000 (8×500) 4,175
Query 37 37
Statistical 483 3,156/3,156 ✓ 5,000 (10×500) 8,639
Text 298 729/733 ⚠ 4,000 (8×500) 5,031
Timezone 47 47
Volatile 0 3,500 (7×500) 3,500
Web 29 56/56 ✓ 6,000 (12×500) 6,085
Total 2,897 10,521/10,527 66,000 (132×500) ~79,424

✓ = 100% passing · ⚠ = known deviation · The ~79,424 total counts formula evaluations (each conformance row and each property case = 1). GitHub Checks reports 3,732 Rust test functions: 2,897 unit + 159 property functions (shown as cases above) + 676 conformance/integration.

@hhimanshu
hhimanshu merged commit 79b478d into main Jul 28, 2026
7 checks passed
@hhimanshu
hhimanshu deleted the fixtures/766-sparkline-rows branch July 28, 2026 03:50
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SPARKLINE: implement the Google Sheets in-cell chart function

1 participant